﻿namespace IPMS.AccessAuth
{
    using System;
    using System.Configuration;
    using System.Data;
    using System.Data.SqlClient;
    using System.Runtime.InteropServices;

    public class Auth
    {
        private string _PageName;
        private string _UserId;
        private string _UserName;

        public Auth(string userId, string userName, string pageName)
        {
            this._UserId = userId;
            this._UserName = userName;
            this._PageName = pageName;
        }

        private void AddParamToSQLCmd(SqlCommand sqlCmd, string paramId, SqlDbType sqlType, int paramSize, ParameterDirection paramDirection, object paramvalue)
        {
            if (sqlCmd == null)
            {
                throw new ArgumentNullException("sqlCmd");
            }
            if (paramId == string.Empty)
            {
                throw new ArgumentOutOfRangeException("paramId");
            }
            SqlParameter newSqlParam = new SqlParameter();
            newSqlParam.ParameterName = paramId;
            newSqlParam.SqlDbType = sqlType;
            newSqlParam.Direction = paramDirection;
            if (paramSize > 0)
            {
                newSqlParam.Size = paramSize;
            }
            if (paramvalue != null)
            {
                newSqlParam.Value = paramvalue;
            }
            sqlCmd.Parameters.Add(newSqlParam);
        }

        public bool CanAdd()
        {
            try
            {
                SqlCommand sqlCmd = new SqlCommand();
                Guid userId = new Guid(this._UserId.ToString());
                this.AddParamToSQLCmd(sqlCmd, "@ReturnValue", SqlDbType.Int, 0, ParameterDirection.ReturnValue, null);
                this.AddParamToSQLCmd(sqlCmd, "@UserId", SqlDbType.UniqueIdentifier, 0, ParameterDirection.Input, userId);
                this.AddParamToSQLCmd(sqlCmd, "@PageName", SqlDbType.NVarChar, 0xff, ParameterDirection.Input, this._PageName.ToString());
                this.AddParamToSQLCmd(sqlCmd, "@CanAdd", SqlDbType.Bit, 0, ParameterDirection.Output, null);
                this.SetCommandType(sqlCmd, CommandType.StoredProcedure, "CanAddSp");
                this.ExecuteScalarCmd(sqlCmd);
                return Convert.ToBoolean(sqlCmd.Parameters["@CanAdd"].Value);
            }
            catch (InvalidCastException)
            {
                return false;
            }
        }

        public bool CanDelete()
        {
            try
            {
                SqlCommand sqlCmd = new SqlCommand();
                Guid userId = new Guid(this._UserId.ToString());
                this.AddParamToSQLCmd(sqlCmd, "@ReturnValue", SqlDbType.Int, 0, ParameterDirection.ReturnValue, null);
                this.AddParamToSQLCmd(sqlCmd, "@UserId", SqlDbType.UniqueIdentifier, 0, ParameterDirection.Input, userId);
                this.AddParamToSQLCmd(sqlCmd, "@PageName", SqlDbType.NVarChar, 0xff, ParameterDirection.Input, this._PageName.ToString());
                this.AddParamToSQLCmd(sqlCmd, "@CanDelete", SqlDbType.Bit, 0, ParameterDirection.Output, null);
                this.SetCommandType(sqlCmd, CommandType.StoredProcedure, "CanDeleteSp");
                this.ExecuteScalarCmd(sqlCmd);
                return Convert.ToBoolean(sqlCmd.Parameters["@CanDelete"].Value);
            }
            catch (InvalidCastException)
            {
                return false;
            }
        }

        public bool CanUpdate()
        {
            try
            {
                SqlCommand sqlCmd = new SqlCommand();
                Guid userId = new Guid(this._UserId.ToString());
                this.AddParamToSQLCmd(sqlCmd, "@ReturnValue", SqlDbType.Int, 0, ParameterDirection.ReturnValue, null);
                this.AddParamToSQLCmd(sqlCmd, "@UserId", SqlDbType.UniqueIdentifier, 0, ParameterDirection.Input, userId);
                this.AddParamToSQLCmd(sqlCmd, "@PageName", SqlDbType.NVarChar, 0xff, ParameterDirection.Input, this._PageName.ToString());
                this.AddParamToSQLCmd(sqlCmd, "@CanUpdate", SqlDbType.Bit, 0, ParameterDirection.Output, null);
                this.SetCommandType(sqlCmd, CommandType.StoredProcedure, "CanUpdateSp");
                this.ExecuteScalarCmd(sqlCmd);
                return Convert.ToBoolean(sqlCmd.Parameters["@CanUpdate"].Value);
            }
            catch (InvalidCastException)
            {
                return false;
            }
        }

        public bool CanView()
        {
            try
            {
                SqlCommand sqlCmd = new SqlCommand();
                Guid userId = new Guid(this._UserId.ToString());
                this.AddParamToSQLCmd(sqlCmd, "@ReturnValue", SqlDbType.Int, 0, ParameterDirection.ReturnValue, null);
                this.AddParamToSQLCmd(sqlCmd, "@UserId", SqlDbType.UniqueIdentifier, 0, ParameterDirection.Input, userId);
                this.AddParamToSQLCmd(sqlCmd, "@PageName", SqlDbType.NVarChar, 0xff, ParameterDirection.Input, this._PageName.ToString());
                this.AddParamToSQLCmd(sqlCmd, "@CanView", SqlDbType.Bit, 0, ParameterDirection.Output, null);
                this.SetCommandType(sqlCmd, CommandType.StoredProcedure, "CanViewSp");
                this.ExecuteScalarCmd(sqlCmd);
                return Convert.ToBoolean(sqlCmd.Parameters["@CanView"].Value);
            }
            catch (InvalidCastException)
            {
                return false;
            }
        }

        private void ExecuteScalarCmd(SqlCommand sqlCmd)
        {
            string ConnectionString = ConfigurationManager.ConnectionStrings["LocalSqlServer"].ConnectionString;
            if (ConnectionString == string.Empty)
            {
                throw new ArgumentOutOfRangeException("ConnectionString");
            }
            if (sqlCmd == null)
            {
                throw new ArgumentNullException("sqlCmd");
            }
            using (SqlConnection cn = new SqlConnection(ConnectionString))
            {
                sqlCmd.Connection = cn;
                cn.Open();
                sqlCmd.ExecuteScalar();
            }
        }

        public int GetAdvAlertDay_SU_Info(out int AdvAlertDay, out bool SuperUser, out string UserRoleName)
        {
            SqlCommand sqlCmd = new SqlCommand();
            this.AddParamToSQLCmd(sqlCmd, "@ReturnValue", SqlDbType.Int, 0, ParameterDirection.ReturnValue, null);
            this.AddParamToSQLCmd(sqlCmd, "@UserName", SqlDbType.NVarChar, 0xff, ParameterDirection.Input, this._UserName.ToString());
            this.AddParamToSQLCmd(sqlCmd, "@AdvAlertDay", SqlDbType.Int, 0, ParameterDirection.Output, null);
            this.AddParamToSQLCmd(sqlCmd, "@SuperUser", SqlDbType.Bit, 0, ParameterDirection.Output, null);
            this.AddParamToSQLCmd(sqlCmd, "@UserRoleName", SqlDbType.NVarChar, 0x100, ParameterDirection.Output, null);
            this.SetCommandType(sqlCmd, CommandType.StoredProcedure, "GetAdvAlertDay_SU_InfoSp");
            try
            {
                this.ExecuteScalarCmd(sqlCmd);
                AdvAlertDay = Convert.ToInt32(sqlCmd.Parameters["@AdvAlertDay"].Value);
                SuperUser = Convert.ToBoolean(sqlCmd.Parameters["@SuperUser"].Value);
                UserRoleName = Convert.ToString(sqlCmd.Parameters["@UserRoleName"].Value);
            }
            catch (Exception)
            {
                AdvAlertDay = 0;
                SuperUser = false;
                UserRoleName = "";
                return -1;
            }
            return Convert.ToInt16(sqlCmd.Parameters["@ReturnValue"].Value);
        }

        public int GetReminderMode()
        {
            SqlCommand sqlCmd = new SqlCommand();
            this.AddParamToSQLCmd(sqlCmd, "@ReturnValue", SqlDbType.Int, 0, ParameterDirection.ReturnValue, null);
            this.AddParamToSQLCmd(sqlCmd, "@ReminderMode", SqlDbType.TinyInt, 0, ParameterDirection.Output, null);
            this.SetCommandType(sqlCmd, CommandType.StoredProcedure, "GetReminderModeSp");
            this.ExecuteScalarCmd(sqlCmd);
            return Convert.ToInt16(sqlCmd.Parameters["@ReminderMode"].Value);
        }

        public string GetRoleName()
        {
            SqlCommand sqlCmd = new SqlCommand();
            Guid userId = new Guid(this._UserId.ToString());
            this.AddParamToSQLCmd(sqlCmd, "@ReturnValue", SqlDbType.Int, 0, ParameterDirection.ReturnValue, null);
            this.AddParamToSQLCmd(sqlCmd, "@UserId", SqlDbType.UniqueIdentifier, 0, ParameterDirection.Input, userId);
            this.AddParamToSQLCmd(sqlCmd, "@RoleName", SqlDbType.NVarChar, 0xff, ParameterDirection.Output, null);
            this.SetCommandType(sqlCmd, CommandType.StoredProcedure, "GetRoleNameSp");
            this.ExecuteScalarCmd(sqlCmd);
            return Convert.ToString(sqlCmd.Parameters["@RoleName"].Value);
        }

        public int GetSystemSetting(out int ReminderMode, out string DocumentRootDirectory)
        {
            SqlCommand sqlCmd = new SqlCommand();
            this.AddParamToSQLCmd(sqlCmd, "@ReturnValue", SqlDbType.Int, 0, ParameterDirection.ReturnValue, null);
            this.AddParamToSQLCmd(sqlCmd, "@ReminderMode", SqlDbType.TinyInt, 0, ParameterDirection.Output, 0);
            this.AddParamToSQLCmd(sqlCmd, "@DocumentRootDirectory", SqlDbType.NVarChar, 100, ParameterDirection.Output, null);
            this.SetCommandType(sqlCmd, CommandType.StoredProcedure, "GetSystemSettingSp");
            this.ExecuteScalarCmd(sqlCmd);
            ReminderMode = Convert.ToInt16(sqlCmd.Parameters["@ReminderMode"].Value);
            DocumentRootDirectory = sqlCmd.Parameters["@DocumentRootDirectory"].Value.ToString();
            return 0;
        }

        public string GetUserId()
        {
            SqlCommand sqlCmd = new SqlCommand();
            this.AddParamToSQLCmd(sqlCmd, "@ReturnValue", SqlDbType.Int, 0, ParameterDirection.ReturnValue, null);
            this.AddParamToSQLCmd(sqlCmd, "@UserName", SqlDbType.NVarChar, 0xff, ParameterDirection.Input, this._UserName.ToString());
            this.AddParamToSQLCmd(sqlCmd, "@UserId", SqlDbType.UniqueIdentifier, 0, ParameterDirection.Output, null);
            this.SetCommandType(sqlCmd, CommandType.StoredProcedure, "GetUserId");
            this.ExecuteScalarCmd(sqlCmd);
            return Convert.ToString(sqlCmd.Parameters["@UserId"].Value);
        }

        public int GetUserInfo(out string RoleName, out bool SuperUser, out int AlertDay)
        {
            SqlCommand sqlCmd = new SqlCommand();
            Guid userId = new Guid(this._UserId.ToString());
            this.AddParamToSQLCmd(sqlCmd, "@ReturnValue", SqlDbType.Int, 0, ParameterDirection.ReturnValue, null);
            this.AddParamToSQLCmd(sqlCmd, "@UserId", SqlDbType.UniqueIdentifier, 0, ParameterDirection.Input, userId);
            this.AddParamToSQLCmd(sqlCmd, "@RoleName", SqlDbType.NVarChar, 0xff, ParameterDirection.Output, null);
            this.AddParamToSQLCmd(sqlCmd, "@SuperUser", SqlDbType.Bit, 0, ParameterDirection.Output, null);
            this.AddParamToSQLCmd(sqlCmd, "@AlertDay", SqlDbType.Int, 4, ParameterDirection.Output, null);
            this.SetCommandType(sqlCmd, CommandType.StoredProcedure, "GetUserInfoSp");
            try
            {
                this.ExecuteScalarCmd(sqlCmd);
                RoleName = Convert.ToString(sqlCmd.Parameters["@RoleName"].Value);
                SuperUser = Convert.ToBoolean(sqlCmd.Parameters["@SuperUser"].Value);
                AlertDay = Convert.ToInt32(sqlCmd.Parameters["@AlertDay"].Value);
            }
            catch (Exception)
            {
                RoleName = "";
                SuperUser = false;
                AlertDay = 0;
                return -1;
            }
            return Convert.ToInt16(sqlCmd.Parameters["@ReturnValue"].Value);
        }

        public int SetAlertAdvDay(string userName, short iDay)
        {
            SqlCommand sqlCmd = new SqlCommand();
            this.AddParamToSQLCmd(sqlCmd, "@ReturnValue", SqlDbType.Int, 0, ParameterDirection.ReturnValue, null);
            this.AddParamToSQLCmd(sqlCmd, "@UserName", SqlDbType.NVarChar, 0x100, ParameterDirection.Input, userName);
            this.AddParamToSQLCmd(sqlCmd, "@AlertAdvDay", SqlDbType.Int, 0, ParameterDirection.Input, iDay);
            this.SetCommandType(sqlCmd, CommandType.StoredProcedure, "SetAlertAdvDaySp");
            this.ExecuteScalarCmd(sqlCmd);
            return Convert.ToInt16(sqlCmd.Parameters["@ReturnValue"].Value);
        }

        private void SetCommandType(SqlCommand sqlCmd, CommandType cmdType, string cmdText)
        {
            sqlCmd.CommandType = cmdType;
            sqlCmd.CommandText = cmdText;
        }

        public int UpdateSystemSetting(int ReminderMode, string DocumentRootDirectory)
        {
            SqlCommand sqlCmd = new SqlCommand();
            this.AddParamToSQLCmd(sqlCmd, "@ReturnValue", SqlDbType.Int, 0, ParameterDirection.ReturnValue, null);
            this.AddParamToSQLCmd(sqlCmd, "@ReminderMode", SqlDbType.TinyInt, 0, ParameterDirection.Input, ReminderMode);
            this.AddParamToSQLCmd(sqlCmd, "@DocumentRootDirectory", SqlDbType.NVarChar, 100, ParameterDirection.Input, DocumentRootDirectory);
            this.SetCommandType(sqlCmd, CommandType.StoredProcedure, "UpdateSystemSettingSp");
            try
            {
                this.ExecuteScalarCmd(sqlCmd);
            }
            catch (Exception)
            {
                return -1;
            }
            return Convert.ToInt16(sqlCmd.Parameters["@ReturnValue"].Value);
        }

        public int UpdateUser(string userName, short iDay, bool bSuperUser)
        {
            SqlCommand sqlCmd = new SqlCommand();
            this.AddParamToSQLCmd(sqlCmd, "@ReturnValue", SqlDbType.Int, 0, ParameterDirection.ReturnValue, null);
            this.AddParamToSQLCmd(sqlCmd, "@UserName", SqlDbType.NVarChar, 0x100, ParameterDirection.Input, userName);
            this.AddParamToSQLCmd(sqlCmd, "@AlertAdvDay", SqlDbType.Int, 0, ParameterDirection.Input, iDay);
            this.AddParamToSQLCmd(sqlCmd, "@SuperUser", SqlDbType.Bit, 0, ParameterDirection.Input, bSuperUser);
            this.SetCommandType(sqlCmd, CommandType.StoredProcedure, "UpdateUserSp");
            try
            {
                this.ExecuteScalarCmd(sqlCmd);
            }
            catch (Exception)
            {
                return -1;
            }
            return Convert.ToInt16(sqlCmd.Parameters["@ReturnValue"].Value);
        }

        public int UpdateUserRole(string role, string newRole, int advAlertDays, bool bSuperUser)
        {
            SqlCommand sqlCmd = new SqlCommand();
            this.AddParamToSQLCmd(sqlCmd, "@ReturnValue", SqlDbType.Int, 0, ParameterDirection.ReturnValue, null);
            this.AddParamToSQLCmd(sqlCmd, "@UserName", SqlDbType.NVarChar, 0x100, ParameterDirection.Input, this._UserName.ToString());
            this.AddParamToSQLCmd(sqlCmd, "@Role", SqlDbType.NVarChar, 0x100, ParameterDirection.Input, role);
            this.AddParamToSQLCmd(sqlCmd, "@NewRole", SqlDbType.NVarChar, 0x100, ParameterDirection.Input, newRole);
            this.AddParamToSQLCmd(sqlCmd, "@AdvAlertDay", SqlDbType.Int, 0, ParameterDirection.Input, advAlertDays);
            this.AddParamToSQLCmd(sqlCmd, "@SuperUser", SqlDbType.Bit, 0, ParameterDirection.Input, bSuperUser);
            this.SetCommandType(sqlCmd, CommandType.StoredProcedure, "UpdateUserRoleSp");
            try
            {
                this.ExecuteScalarCmd(sqlCmd);
            }
            catch (Exception)
            {
                return -1;
            }
            return Convert.ToInt16(sqlCmd.Parameters["@ReturnValue"].Value);
        }
    }
}

